/*
 * Copyright 2012 Finbudget.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package finbudgettable.client.ui.grid.cell.attachment;

import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.i18n.client.Messages;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.PopupPanel;
import finbudget.client.ui.widget.upload.Attachment;
import finbudget.client.ui.widget.upload.UploadWidget;
import finbudget.shared.Constants;
import finbudgettable.client.ui.grid.Utils;
import finbudgettable.client.ui.grid.cell.AbstractPopupCell;

import java.util.ArrayList;
import java.util.List;

public class AttachmentCell extends AbstractPopupCell<UploadWidget.UploadWidgetParams, AttachmentCellEditor> {

    interface Templates extends SafeHtmlTemplates {

        @Template("<a href=\"{0}\">{1}</a>")
        SafeHtml link(SafeUri url, String name);

        @Template(" __ <a class=\"{0}\" href=\"\">{1}</a>")
        SafeHtml more(String className, String moreMessage);

        @Template("<br>")
        SafeHtml br();

        @Template("{0}")
        SafeHtml empty(String message);

        @Template("<div class=\"{0}\">{1}</div>")
        SafeHtml innerDiv(String className, SafeHtml content);

    }

    interface Resources extends ClientBundle {

        interface Style extends CssResource {

            @ClassName("b-attachment-cell__more-link")
            String bAttachmentCell__moreLink();

            @ClassName("b-attachment-cell")
            String bAttachmentCell();

            @ClassName("b-attachment-cell__text")
            String bAttachmentCell__text();

            @ClassName("b-attachment-cell__multiline_text")
            String bAttachmentCell__multiline_text();
        }

        @Source("AttachmentCell.css")
        Style style();

        @Source("delete.png")
        ImageResource deleteImage();

        @Source("deleting.png")
        ImageResource deletingImage();

    }

    interface Strings extends Messages {

        @DefaultMessage("Ещё {0}")
        String more(int qty);

        @DefaultMessage("Нет вложений")
        String noAttachments();

    }

    private static final Templates TEMPLATES = GWT.create(Templates.class);

    static final Strings STRINGS = GWT.create(Strings.class);
    static final Resources RESOURCES = GWT.create(Resources.class);

    static {
        RESOURCES.style().ensureInjected();
    }

    public AttachmentCell(UploadWidget.UploadWidgetFactory factory) {
        super(new AttachmentCellEditor(factory));
    }

    private String getAttachmentUrl(Attachment attachment){
        UrlBuilder builder = Window.Location.createUrlBuilder();
        builder = builder.setPath(Constants.urlDownload);
        builder = builder.setHash(null);
        builder = builder.setParameter(Constants.paramBlob, attachment.getBlobKey());
        return builder.buildString();
    }

    @Override
    protected void render(Context context, UploadWidget.UploadWidgetParams params,
                          UploadWidget.UploadWidgetParams viewData, SafeHtmlBuilder sb) {
//        Object key = context.getKey();
        List<Attachment> atts = getAttachments(params.value);
        if (atts.isEmpty()) {
            sb.append(TEMPLATES.innerDiv(getInnerCellStyle(), TEMPLATES.empty(STRINGS.noAttachments())));
            return;
        }
        SafeHtmlBuilder innerBuilder = new SafeHtmlBuilder();
        if (isMultilineStyle()) {
            for (Attachment attachment : atts) {
                SafeUri url = UriUtils.fromSafeConstant(getAttachmentUrl(attachment));
                innerBuilder.append(TEMPLATES.link(url, attachment.getFileName()));
                innerBuilder.append(TEMPLATES.br());
            }
        } else {
            Attachment attachment = atts.get(0);
            SafeUri url = UriUtils.fromSafeConstant(getAttachmentUrl(attachment));
            innerBuilder.append(TEMPLATES.link(url, attachment.getFileName()));
            if (atts.size() > 1) {
                innerBuilder.append(TEMPLATES.more(RESOURCES.style().bAttachmentCell__moreLink(), STRINGS.more(atts.size() - 1)));
            }
        }
        sb.append(TEMPLATES.innerDiv(getInnerCellStyle(), innerBuilder.toSafeHtml()));
    }

    private String getInnerCellStyle() {
        if (isMultilineStyle()) {
            return RESOURCES.style().bAttachmentCell__multiline_text();
        } else {
            return RESOURCES.style().bAttachmentCell__text();
        }
    }

    @Override
    protected void popup(final AttachmentCellEditor editor) {
        String value = getLastValue().value;
        if (!isReadonly() || (value != null && !value.isEmpty())) {
            editor.setReadOnly(isReadonly());
            editor.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
                @Override
                public void setPosition(int offsetWidth, int offsetHeight) {
                    editor.setPopupPosition(
                            getLastParent().getParentElement().getAbsoluteLeft() - 1,
                            getLastParent().getParentElement().getAbsoluteTop() - 1);
                    Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
                        @Override
                        public void execute() {
                            editor.focus();
                        }
                    });
                }
            });
        }
    }

    @Override
    public void onBrowserEvent(Context context, Element parent, UploadWidget.UploadWidgetParams value, NativeEvent event,
                               ValueUpdater<UploadWidget.UploadWidgetParams> updater) {
        String type = event.getType();
        if (BrowserEvents.CLICK.equals(type)) {
            EventTarget target = event.getEventTarget();
            if (Element.is(target)) {
                Element el = target.cast();
                if (el.getTagName().equalsIgnoreCase("a")) {
                    if (Utils.hasClassName(el, RESOURCES.style().bAttachmentCell__moreLink())) {
                        startEdit(context, parent, value, event, updater);
                        event.preventDefault();
                    }
                    return;
                }
            }
        }
        super.onBrowserEvent(context, parent, value, event, updater);
    }
//
//    @Override
//    protected boolean canShowEditor() {
//        return true;
//    }

    private List<Attachment> getAttachments(String value) {
        List<Attachment> result = new ArrayList<Attachment>();
        if (value != null) {
            for (String strValue : value.split(" ")) {
                if (!strValue.isEmpty()) {
                    result.add(new Attachment(strValue));
                }
            }
        }
        return result;
    }
}
